package com.witframework.util;

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
/**
 * 
 * @author wuxinyang
 * Sep 4, 2009 4:43:57 PM
 *
 */
public class ExpiringMap extends ConcurrentHashMap{
  private static final long serialVersionUID = 100L;
  long expiration_time;
  boolean stop_thread;
  ExpiringMap thisInstance = this;

  public ExpiringMap(long expiration_time) {
    this.expiration_time = expiration_time;

    if (expiration_time > 0L)
      new TimedCleanup(this).start();
  }

  public Object get(Object key){
    TimedMapObject t_obj = (TimedMapObject)super.get(key);
    if (t_obj != null)
      return t_obj.getObject();
    return null;
  }

  public Object put(Object key, Object obj){
    TimedMapObject t_obj = (TimedMapObject)super.put(key, new TimedMapObject(obj));
    if (t_obj != null)
      return t_obj.getObject();
    return null;
  }  

  protected void finalize(){
    this.stop_thread = true;
  }

  public static void main(String[] args){
    ExpiringMap map = new ExpiringMap(1000L);
    for (int i = 0; i < 100; ++i){
      map.put("test" + i, "this is a test" + i);
      System.out.println(map.get("test" + i));
      try { 
    	  Thread.sleep(500L); 
      } catch (InterruptedException e) { }
      System.out.println(map.size());
    }
    System.exit(0);
  }
  static class TimedMapObject{
    long time = System.currentTimeMillis();
    Object obj;
    TimedMapObject(Object obj){
      this.obj = obj; 
    }
    long getTime() {
      return this.time;
    }
    Object getObject() {
      this.time = System.currentTimeMillis();
      return this.obj;
    }
  }
  class TimedCleanup extends Thread{
	ExpiringMap expiringMap;
	public  TimedCleanup(ExpiringMap expiringMap){
		  this.expiringMap=expiringMap;
	}
    public void run(){
      while (!(expiringMap.stop_thread)) {
        try {
          sleep(5000L); } catch (InterruptedException ex) {
        }
        Iterator it = expiringMap.thisInstance.entrySet().iterator();

        while (it.hasNext()){
          java.util.Map.Entry entry = (java.util.Map.Entry)it.next();
          ExpiringMap.TimedMapObject t_obj = (ExpiringMap.TimedMapObject)entry.getValue();
          if (System.currentTimeMillis() - t_obj.getTime() > expiringMap.expiration_time)
            it.remove();
        }
      }
    }
  }
}
